#include "own_chip_rtc.h"
#include "device_resource.h"
#include "print_rtt.h"
void own_chip_rtc_init(void)
{
  // 秒 0-60，分 0-59，时 0-23，日 1-31，月 0-11，年 −1900，周日 0，夏令 -1/0/1”。
  struct tm currnt_time_st, *tm_p;
  uint8_t hour, min, sec;
  uint8_t week, day, month, year;
  RTC_Init_LSI_1min();

  // 日期：周一(1)～周日(7)，月(1-12)，日(1-31)，年(0-99)。
  // 时间：秒/分(0-59)，时(0-23 或 1-12)，12 h 模式再补 AM/PM。
  OWN_CHIP_RTC_GetDate(&year, &month, &day, &week);
  OWN_CHIP_RTC_GetTime(&hour, &min, &sec);
  LOG_COLOR(YELLOW, "RTC: %d-%d-%d (%d) %d:%d:%d\n", year, month, day, week, hour, min, sec);
  rtc_vals_to_tm(year, month, day, hour, min, sec, week, &currnt_time_st);

  device_time_tickets = mktime(&currnt_time_st);
  if ((device_time_tickets < 1760227200) && (device_time_tickets < 3022243200))
  {
    device_time_tickets = 1760227200;
  }
  device_time_ms_tickets = ((uint64_t)device_time_tickets) * 1000;
  tm_p = localtime(&device_time_tickets);
  tm_to_rtc_vals(tm_p, &year, &month, &day, &hour, &min, &sec, &week);
  LOG_INFO("ticket time: %d-%d-%d (%d) %d:%d:%d\n", year, month, day, week, hour, min, sec);
  LOG_COLOR(YELLOW, "set RTC: %d-%d-%d (%d) %d:%d:%d\n", year, month, day, week, hour, min, sec);
  OWN_CHIP_RTC_SetDate(year, month, day, week);
  OWN_CHIP_RTC_SetTime(hour, min, sec);
  TIM1_Init_1ms();
}
void own_chip_rtc_cycle(void)
{
  uint8_t hour, min, sec;
  uint8_t week, day, month, year;
  struct tm *p;
  device_time_tickets = (time_t)((uint64_t)device_time_ms_tickets / 1000);
  LOG_INFO("tickets: %ld\n", device_time_tickets);
  // OWN_CHIP_RTC_GetDate(&year, &month, &day, &week);
  // OWN_CHIP_RTC_GetTime(&hour, &min, &sec);
  // LOG_INFO("RTC: %d-%d-%d (%d) %d:%d:%d\n", year, month, day, week, hour, min, sec);
  p = localtime(&device_time_tickets);
  // device_time_tickets = loc(currnt_time_st

  tm_to_rtc_vals(p, &year, &month, &day, &hour, &min, &sec, &week);
  LOG_INFO("tickets: %d-%d-%d (%d) %d:%d:%d\n", year, month, day, week, hour, min, sec);
  OWN_CHIP_RTC_SetTime(hour, min, sec);
  LOG_COLOR(YELLOW, "rtc : %d:%d:%d\n", hour, min, sec);
}
/*----------------------------------------------------------
 * 用户接口：初始化 RTC（LSI 为时钟源，60 s 唤醒一次）
 *---------------------------------------------------------*/
void RTC_Init_LSI_1min(void)
{
  /* 1. 允许备份域访问 */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
  PWR_BackupAccessCmd(ENABLE);

  /* 2. 使能 LSI 并等待稳定 */
  RCC_LSICmd(ENABLE);
  while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
    ;

  /* 3. 选 LSI 为 RTC 时钟源，并开启 RTC */
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
  RCC_RTCCLKCmd(ENABLE);

  /* 4. 等待 RTC 寄存器同步 */
  RTC_WaitForSynchro();

  /* 5. 配置分频与 24h 格式 */
  RTC_Config();

  /* 6. 配置唤醒中断（60 s）*/
  RTC_WakeUpCmd(DISABLE);                                /* 先关闭才能改时钟源 */
  RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits); /* ck_spre = 1 Hz */
  RTC_SetWakeUpCounter(59);                              /* 60 个 1 Hz 周期 = 60 s */

  RTC_ITConfig(RTC_IT_WUT, ENABLE); /* 使能唤醒中断 */
  RTC_WakeUpCmd(ENABLE);            /* 启动唤醒定时器 */

  /* 7. 配置 NVIC + EXTI */
  RTC_NVIC_Config();
}

/*----------------------------------------------------------
 * RTC 基础配置：分频 + 24h 格式
 *---------------------------------------------------------*/
static void RTC_Config(void)
{
  RTC_InitTypeDef rtc;
  rtc.RTC_HourFormat = RTC_HourFormat_24;
  rtc.RTC_AsynchPrediv = 127; /* 32 kHz /128 = 256 Hz */
  rtc.RTC_SynchPrediv = 249;  /* 256 Hz /250 = 1.024 Hz ≈1 Hz */
  RTC_Init(&rtc);
}

/*----------------------------------------------------------
 * 中断控制器：RTC_WKUP + EXTI22
 *---------------------------------------------------------*/
static void RTC_NVIC_Config(void)
{
  EXTI_InitTypeDef exti;
  NVIC_InitTypeDef nvic;

  EXTI_ClearITPendingBit(EXTI_Line22);
  exti.EXTI_Line = EXTI_Line22;
  exti.EXTI_Mode = EXTI_Mode_Interrupt;
  exti.EXTI_Trigger = EXTI_Trigger_Rising;
  exti.EXTI_LineCmd = ENABLE;
  EXTI_Init(&exti);

  nvic.NVIC_IRQChannel = RTC_WKUP_IRQn;
  nvic.NVIC_IRQChannelPreemptionPriority = 0;
  nvic.NVIC_IRQChannelSubPriority = 0;
  nvic.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&nvic);
  RTC_ClearFlag(RTC_FLAG_WUTF);
  EXTI_ClearITPendingBit(EXTI_Line22);
  // RTC_WakeUp_EXTILineConfig();
}

/*----------------------------------------------------------
 * 中断服务函数：每分钟进来一次
 *---------------------------------------------------------*/

/* -------------- 时间写入 -------------- */
void OWN_CHIP_RTC_SetTime(uint8_t hour, uint8_t min, uint8_t sec)
{
  RTC_TimeTypeDef sTime = {0};
  sTime.RTC_Hours = hour;
  sTime.RTC_Minutes = min;
  sTime.RTC_Seconds = sec;
  RTC_SetTime(RTC_Format_BIN, &sTime); /* 库函数自动把 BIN→BCD */
}

/* -------------- 时间读取 -------------- */
void OWN_CHIP_RTC_GetTime(uint8_t *hour, uint8_t *min, uint8_t *sec)
{
  RTC_TimeTypeDef sTime = {0};
  RTC_GetTime(RTC_Format_BIN, &sTime); /* 库函数把 BCD→BIN */
  *hour = sTime.RTC_Hours;
  *min = sTime.RTC_Minutes;
  *sec = sTime.RTC_Seconds;
}

/* -------------- 日期写入 -------------- */
void OWN_CHIP_RTC_SetDate(uint8_t year, uint8_t month, uint8_t date, uint8_t week)
{
  RTC_DateTypeDef sDate = {0};
  sDate.RTC_Year = year; /* 0=2000, 1=2001 … 99=2099 */
  sDate.RTC_Month = month;
  sDate.RTC_Date = date;
  sDate.RTC_WeekDay = week; /* 1=Monday … 7=Sunday */
  RTC_SetDate(RTC_Format_BIN, &sDate);
}

/* -------------- 日期读取 -------------- */
void OWN_CHIP_RTC_GetDate(uint8_t *year, uint8_t *month, uint8_t *date, uint8_t *week)
{
  RTC_DateTypeDef sDate = {0};
  RTC_GetDate(RTC_Format_BIN, &sDate);
  *year = sDate.RTC_Year;
  *month = sDate.RTC_Month;
  *date = sDate.RTC_Date;
  *week = sDate.RTC_WeekDay;
}
void TIM1_Init_1ms(void)
{
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
  TIM1_Config();
  TIM1_NVIC_Config();
}

static void TIM1_Config(void)
{
  TIM_TimeBaseInitTypeDef tim;
  TIM_DeInit(TIM1);

  tim.TIM_Prescaler = 168 - 1; // 168 MHz / 168 = 1 MHz
  tim.TIM_CounterMode = TIM_CounterMode_Up;
  tim.TIM_Period = 1000 - 1; // 1 MHz / 1000 = 1 kHz
  tim.TIM_ClockDivision = TIM_CKD_DIV1;
  tim.TIM_RepetitionCounter = 0; // 高级定时器特有，必须给 0
  TIM_TimeBaseInit(TIM1, &tim);

  TIM_ClearFlag(TIM1, TIM_FLAG_Update);
  TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
  TIM_Cmd(TIM1, ENABLE); // 启动
}

static void TIM1_NVIC_Config(void)
{
  NVIC_InitTypeDef nvic;
  nvic.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn;
  nvic.NVIC_IRQChannelPreemptionPriority = 0;
  nvic.NVIC_IRQChannelSubPriority = 0;
  nvic.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&nvic);
}

/* 中断服务函数 */
void rtc_vals_to_tm(uint8_t year, uint8_t mon, uint8_t day,
                    uint8_t hour, uint8_t min, uint8_t sec,
                    uint8_t wday, struct tm *tm)
{
  tm->tm_year = year + 100; // 2000→1900
  tm->tm_mon = mon - 1;     // 1-12→0-11
  tm->tm_mday = day;
  tm->tm_hour = hour;
  tm->tm_min = min;
  tm->tm_sec = sec;
  tm->tm_wday = (wday + 5) % 7; // 1-7→0-6
  tm->tm_isdst = -1;            // 让系统自行判断夏令时
}

/* ---------- tm → 散值 ---------- */
void tm_to_rtc_vals(const struct tm *tm,
                    uint8_t *year, uint8_t *mon, uint8_t *day,
                    uint8_t *hour, uint8_t *min, uint8_t *sec,
                    uint8_t *wday)
{
  *year = tm->tm_year - 100; // 1900→2000
  *mon = tm->tm_mon + 1;     // 0-11→1-12
  *day = tm->tm_mday;
  *hour = tm->tm_hour;
  *min = tm->tm_min;
  *sec = tm->tm_sec;
  *wday = (tm->tm_wday + 1) % 7 + 1; // 0-6→1-7
}
